package org.softmed.neodatis.util.reflection;

import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.softmed.reflection.utils.ReflectionUtil;

public class ClassIDFieldRegistration {

	Map<Class, ClassGeneratedFieldInfo> classFieldInfo = new HashMap<Class, ClassGeneratedFieldInfo>();
	List<Class> disabledAllInheritedGeneratedFields = new ArrayList<Class>();
	Map<Class, ClassGeneratedFieldInfo> disabledInheritedGeneratedFields = new HashMap<Class, ClassGeneratedFieldInfo>();

	ReflectionUtil util = new ReflectionUtil();

	public void disableAllInheritedGeneratedFields(Class type) {
		disabledAllInheritedGeneratedFields.add(type);
	}

	public void disableInheritedGeneratedField(Class type, String fieldName)
			throws Throwable {
		ReflectionUtil util = new ReflectionUtil();

		Method getter = util.getGetter(type, fieldName);
		Method setter = util.getSetter(type, getter.getReturnType(), fieldName);

		if (getter.getParameterTypes().length > 0)
			throw new RuntimeException(
					"No legal getter method found for ID field " + fieldName
							+ "  of class " + type
							+ " : method can't have parameters !!!");

		if (setter.getParameterTypes().length != 1)
			throw new RuntimeException(
					"No legal setter method found for ID field " + fieldName
							+ "  of class " + type
							+ " : method must have only one parameter");

		ClassGeneratedFieldInfo info = disabledInheritedGeneratedFields
				.get(type);
		if (info == null) {
			info = new ClassGeneratedFieldInfo();
			disabledInheritedGeneratedFields.put(type, info);
		}

		Class<?> paramType = setter.getParameterTypes()[0];
		// info.registerField(fieldName, getter, setter, paramType);
		info.registerField(util.getFieldInfo(type, fieldName), fieldName);
	}

	public void register(Class type, String fieldName) throws Throwable {
		ReflectionUtil util = new ReflectionUtil();

		Method getter = util.getGetter(type, fieldName);
		Method setter = util.getSetter(type, getter.getReturnType(), fieldName);

		if (getter.getParameterTypes().length > 0)
			throw new RuntimeException(
					"No legal getter method found for ID field " + fieldName
							+ "  of class " + type
							+ " : method can't have parameters !!!");

		if (setter.getParameterTypes().length != 1)
			throw new RuntimeException(
					"No legal setter method found for ID field " + fieldName
							+ "  of class " + type
							+ " : method must have only one parameter");

		ClassGeneratedFieldInfo info = classFieldInfo.get(type);
		if (info == null) {
			info = new ClassGeneratedFieldInfo();
			classFieldInfo.put(type, info);
		}

		Class<?> paramType = setter.getParameterTypes()[0];
		// info.registerField(fieldName, getter, setter, paramType);
		info.registerField(util.getFieldInfo(type, fieldName), fieldName);

	}

	public List<Class> getDisabledAllInheritedGeneratedFields() {
		return disabledAllInheritedGeneratedFields;
	}

	public boolean areAllInheritedGeneratedFieldsDisabled(Class type) {
		return disabledAllInheritedGeneratedFields.contains(type);
	}

	public Map<Class, ClassGeneratedFieldInfo> getClassFieldInfo() {
		return classFieldInfo;
	}

	public ClassGeneratedFieldInfo getClassFieldInfo(Class type) {
		return classFieldInfo.get(type);
	}

	public Map<Class, ClassGeneratedFieldInfo> getDisabledInheritedGeneratedFields() {
		return disabledInheritedGeneratedFields;
	}

	public ClassGeneratedFieldInfo getDisabledInheritedGeneratedFields(
			Class type) {
		return disabledInheritedGeneratedFields.get(type);
	}

}
